package com.tbit.uqbike.client.controller.interceptor;


import com.tbit.uqbike.client.service.TokenService;
import com.tbit.uqbike.client.util.DateTimeUtil;
import com.tbit.uqbike.client.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.TimeZone;

/**
 * @Author: chen
 * @Description: 时区拦截器
 * @Date: 创建于 14:16 2019/12/27
 */

@Intercepts(
        @Signature(method = "query",
                type = Executor.class,
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
        )
)
@Component
@Slf4j
public class TimeZoneInterceptor implements Interceptor {

    @Autowired
    private TokenService tokenService;

    /**
     * 时区转化
     *
     * @param time           时间
     * @param NowTimeZone    当前时区
     * @param TargetTimeZone 目标时区
     * @return
     */
    private static String timeTransfer(String time, String NowTimeZone, String TargetTimeZone) {
        if (time == null) {
            return "";
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone(NowTimeZone));
        Date date;
        try {
            date = simpleDateFormat.parse(time);
        } catch (ParseException e) {
            return "0";
        }
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone(TargetTimeZone));
        return simpleDateFormat.format(date);
    }

    public static void main(String[] args) {
        System.out.println(TimeZone.getDefault().getID());
        System.out.println(timeTransfer("2019-11-01 00:00:00", TimeZone.getDefault().getID(), "GMT+02:00"));
    }

    /**
     * 拦截器拦截操作
     *
     * @param invocation
     * @return
     */
    @Override
    public Object intercept(Invocation invocation) {

        Object proceed = null;
        try {
            //获取操作对象
            proceed = invocation.proceed();
            MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];


            /**
             * 下面这些值（返回值类型、返回实力类...）可以在上一行打个断点看一下具体代表什么，
             * 然后根据自己的需要获取到方法名或者返回实体类进行拦截和修改
             */

            //获取返回值类型
            String returnType = invocation.getMethod().getReturnType().getName();

            //获取返回实体类
            String resultMap = mappedStatement.getResultMaps().get(0).getType().getName();

            //方法路径和名称
            String methodPathName = mappedStatement.getId();

            //注解中method的值
            String methodName = invocation.getMethod().getName();
            //sql类型
            SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
            /**自定义拦截方法*/
            //TimeTransType timeTransType = TimeTransType.find(returnType,resultMap,methodPathName);

            /*if (timeTransType != null){
             *//**拦截查询操作*//*
        if ("query".equals(methodName)) {
          //对有要求的字段填值
          if (SqlCommandType.SELECT.equals(sqlCommandType)) {
            switch (timeTransType){
              case TYPE1:
                List<Object> list = (List<Object>) proceed;
                System.out.println("输出前"+list);
                for (Object obj : list) {
                  setFieldValue(obj);
                  System.out.println("转化后"+list);
                }
                break;
            }
            log.info("[时区时间转换成功]timezone transform success!");
          }
        }
      }*/

            /**拦截查询操作*/
            if ("query".equals(methodName)) {
                //对有要求的字段填值
                if (SqlCommandType.SELECT.equals(sqlCommandType) && !resultMap.equals("java.lang.Integer")) {
                    List<Object> list = (List<Object>) proceed;
                    if (list.size() > 0) {
                        for (Object obj : list) {
                            /**转化时区,重新设置*/
                            setFieldValue(obj);
                        }
                    }
                }
            }
        } catch (Exception e) {
            //log.error("[时区实践转换失败]timezone transform error",e);
            //log.error(e.getMessage(), e);
        }
        return proceed;
    }

    /**
     * @param target 表示被拦截的对象，此处为 Executor 的实例对象
     *               作用：如果被拦截对象所在的类有实现接口，就为当前拦截对象生成一个代理对象
     *               如果被拦截对象所在的类没有指定接口，这个对象之后的行为就不会被代理操作
     * @return
     */
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }

    /**
     * 反射设值
     *
     * @param obj
     * @throws Exception
     */
    public void setFieldValue(Object obj) throws Exception {
        Field[] fields = obj.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            /**属性类型为时间，需要转化*/
      /*if(fields[i].getType().getName().equals("java.util.Date")){
        //Field fieldName = obj.getClass().getDeclaredField(field);
        *//**获取属性值*//*
        Date value= (Date) ObjectUtil.getFieldValueByName(fields[i].getName(), obj);
        *//**转化时区*//*
        String date= timeTransfer(DateUtils.formatDate(value),TimeZone.getDefault().getID(),"GMT+02:00");
        *//**设置可修改*//*
        fields[i].setAccessible(true);
        *//**修改属性值*//*
        fields[i].set(obj, DateUtils.parseDate(date));
      }*/

            if (ObjectUtil.getFieldValueByName(fields[i].getName(), obj) != null && DateTimeUtil.isDateString(ObjectUtil.getFieldValueByName(fields[i].getName(), obj).toString())) {
                /**获取属性值*/

                Date value = DateTimeUtil.StringToDateTime(ObjectUtil.getFieldValueByName(fields[i].getName(), obj).toString());

                /**获取对象*/
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                HttpSession session = request.getSession();

                /**获取对象时区*/
                String timeZoneId = session.getAttribute("timeZone").toString();
                /**转化时区*/
                String date = timeTransfer(ObjectUtil.getFieldValueByName(fields[i].getName(), obj).toString(), TimeZone.getDefault().getID(), timeZoneId);

                /**设置可修改*/
                fields[i].setAccessible(true);
                /**修改属性值*/
                fields[i].set(obj, date);
            }

        }
    }

}
